import G6, { Util } from '@antv/g6';
export function getAnchorName(anchor: [number, number]): string {
  if (anchor[0] === 0.33 && anchor[1] === 0) {
    return '入参口';
  }
  if (anchor[0] === 0.66 && anchor[1] === 0) {
    return '起始点';
  }
  if (anchor[0] === 0.33 && anchor[1] === 1) {
    return '输出口';
  }
  if (anchor[0] === 0.66 && anchor[1] === 1) {
    return '结束点';
  }
}

export function getAnchorType(anchor: [number, number]): string {
  if (anchor[0] === 0.33 && anchor[1] === 0) {
    return 'input';
  }
  if (anchor[0] === 0.66 && anchor[1] === 0) {
    return 'executeEntry';
  }
  if (anchor[0] === 0.33 && anchor[1] === 1) {
    return 'output';
  }
  if (anchor[0] === 0.66 && anchor[1] === 1) {
    return 'executeExit';
  }
}

export function getNodeThemeColor(unitType: string): string {
  switch (unitType) {
    case 'DPU':
      return '#fa983a';
    case 'INIT_DU':
      return '#30BF78';
  }
}

const ICON_MAP = {
  // eslint-disable-next-line @typescript-eslint/naming-convention
  DPU: '/assets/images/func.svg',
  // eslint-disable-next-line @typescript-eslint/naming-convention
  INIT_DU: '/assets/images/var.svg',
};
export class CardNode {
  // eslint-disable-next-line @typescript-eslint/naming-convention
  public static readonly NODE_NAME = 'card-node';
  // eslint-disable-next-line @typescript-eslint/naming-convention
  public static readonly NODE_DEFINTION = {
    drawShape: function drawShape(cfg, group) {
      const mainBoxStokeWith: number = cfg.style.lineWidth
        ? cfg.style.lineWidth
        : 1;
      const r = 2;
      const color = cfg.themeColor;
      const shape = group.addShape('rect', {
        attrs: {
          x: 0,
          y: 0,
          width: 200,
          height: 60,
          stroke: color,
          fill: '#dff9fb',
          cursor: 'move',
          lineWidth: mainBoxStokeWith,
          radius: r,
        },
        name: 'main-box',
        draggable: true,
      });

      group.addShape('rect', {
        attrs: {
          x: 0,
          y: 0,
          width: 200,
          height: 20,
          fill: color,
          cursor: 'move',
          radius: [r, r, 0, 0],
        },
        name: 'title-box',
        draggable: true,
      });

      // left icon
      group.addShape('image', {
        attrs: {
          x: 4,
          y: 2,
          height: 16,
          width: 16,
          cursor: 'pointer',
          img: ICON_MAP[(cfg.unitType as any) || 'DPU'],
        },
        name: 'node-icon',
      });

      // title text
      group.addShape('text', {
        attrs: {
          textBaseline: 'top',
          y: 5,
          x: 24,
          lineHeight: 20,
          text: cfg.unitType,
          fill: '#fff',
        },
        name: 'title',
      });

      // value text
      group.addShape('text', {
        attrs: {
          textBaseline: 'top',
          y: 30,
          x: 100,
          lineHeight: 20,
          fontWeight: 'bold',
          fontSize: 20,
          text: cfg.title,
          textAlign: 'center',
          fill: '#595959',
        },
      });

      if (cfg.animation) {
        group.addShape(
          'image',
          {
            attrs: {
              y: 30,
              x: 20,
              height: 16,
              width: 16,
              cursor: 'pointer',
              img: '/assets/images/error.svg',
            },
          },
          'info-icon'
        );
      }

      if (cfg.entryPoint) {
        group.addShape(
          'image',
          {
            attrs: {
              y: 30,
              x: 20,
              height: 30,
              width: 30,
              cursor: 'pointer',
              img: '/assets/images/start.svg',
            },
          },
          'info-icon'
        );
      }
      // group.addShape('circle', {
      //   attrs: {
      //     y: 10,
      //     x: 170,
      //     r: 5,
      //     fill: 'red',
      //   },
      // });

      group.addShape('path', {
        attrs: {
          path: [
            ['M', 185, 10],
            ['L', 198, 10],
          ],
          stroke: '#ecf0f1',
          lineWidth: 3,
          cursor: 'pointer',
        },
        name: 'delete-node',
      });
      const paths = [['M', 0, 60]];

      for (let i = 5; i < 205; i = i + 5) {
        paths.push(['L', i, (i / 5) % 2 === 0 ? 55 : 60]);
      }
      group.addShape('path', {
        attrs: {
          path: [...paths],
          stroke: '#eb4d4b',
          lineWidth: 2,
          cursor: 'pointer',
        },
        name: 'error-line',
      });

      return shape;
    },
    // draw anchor-point circles according to the anchorPoints in afterDraw
    afterDraw(cfg, group) {
      console.log('====animation begin====');
      console.log(group);
      if (cfg.animation) {
        const shape = group.get('children')[5];
        shape.animate(
          (ratio) => {
            const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
            return {
              height: 5 * 2 + diff,
              width: 5 * 2 + diff,
            };
          },
          {
            repeat: true,
            duration: 3000,
            easing: 'easeCubic',
          }
        );
      }

      if (cfg.entryPoint) {
        const shape = group.get('children')[5];
        shape.animate(
          (ratio) => {
            const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
            return {
              height: 9 * 2 + diff,
              width: 9 * 2 + diff,
            };
          },
          {
            repeat: true,
            duration: 3000,
            easing: 'easeCubic',
          }
        );
      }

      const bbox = group.getBBox();
      const anchorPoints = this.getAnchorPoints(cfg);
      anchorPoints.forEach((anchorPos, i) => {
        switch (cfg.unitType) {
          case 'DPU':
            if (anchorPos[1] === 0 || anchorPos[1] === 1) {
              group.addShape('rect', {
                attrs: {
                  width: 30,
                  height: 20,
                  radius: anchorPos[1] === 0 ? [4, 4, 0, 0] : [0, 0, 4, 4],
                  x: bbox.x + bbox.width * anchorPos[0] - 15,
                  y:
                    anchorPos[1] === 0
                      ? bbox.y + bbox.height * anchorPos[1] - 20
                      : bbox.y + bbox.height * anchorPos[1],
                  fill: '#ecf0f1',
                  stroke: '#5F95FF',
                  cursor: 'grabbing',
                },
                name: `anchor-point`, // the name, for searching by group.find(ele => ele.get('name') === 'anchor-point')
                anchorPointIdx: i, // flag the idx of the anchor-point circle
                links: 0, // cache the number of edges connected to this shape
                visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state
                draggable: true, // allow to catch the drag events on this shape
                anchorType: getAnchorType(anchorPos),
              });
              group.addShape('text', {
                attrs: {
                  text: getAnchorName(anchorPos),
                  fill: '#a4b0be',
                  fontSize: 10,
                  x: bbox.x + bbox.width * anchorPos[0] - 15,
                  y:
                    anchorPos[1] === 0
                      ? bbox.y + bbox.height * anchorPos[1] - 2
                      : bbox.y + bbox.height * anchorPos[1] + 20 - 2,
                },
                // must be assigned in G6 3.3 and later versions. it can be any value you wantPath
                name: 'anchor-text',
                visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state
                draggable: true, // allow to catch the drag events on this shape
              });
            }
            break;
          case 'INIT_DU':
            group.addShape('rect', {
              attrs: {
                width: 50,
                height: 20,
                radius: anchorPos[1] === 0 ? [4, 4, 0, 0] : [0, 0, 4, 4],
                x: bbox.x + bbox.width * anchorPos[0] - 15 - 5,
                y:
                  anchorPos[1] === 0
                    ? bbox.y + bbox.height * anchorPos[1] - 20
                    : bbox.y + bbox.height * anchorPos[1],
                fill: '#ecf0f1',
                stroke: '#5F95FF',
                cursor: 'grabbing',
              },
              name: `anchor-point`, // the name, for searching by group.find(ele => ele.get('name') === 'anchor-point')
              anchorPointIdx: i, // flag the idx of the anchor-point circle
              links: 0, // cache the number of edges connected to this shape
              visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state
              draggable: true, // allow to catch the drag events on this shape
              anchorType: 'INIT_DU_OUT_POINT',
            });
            group.addShape('text', {
              attrs: {
                text: '数据出口',
                fill: '#a4b0be',
                fontSize: 10,
                x: bbox.x + bbox.width * anchorPos[0] - 15,
                y:
                  anchorPos[1] === 0
                    ? bbox.y + bbox.height * anchorPos[1] - 2
                    : bbox.y + bbox.height * anchorPos[1] + 20 - 2,
              },
              // must be assigned in G6 3.3 and later versions. it can be any value you wantPath
              name: 'anchor-text',
              visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state
              draggable: true, // allow to catch the drag events on this shape
            });

            break;
        }
      });
    },
    getAnchorPoints(cfg) {
      if (cfg.unitType === 'DPU') {
        return (
          cfg.anchorPoints || [
            [0, 0.5],
            [0.33, 0],
            [0.66, 0],
            [1, 0.5],
            [0.33, 1],
            [0.66, 1],
          ]
        );
      } else {
        return cfg.anchorPoints || [[0.5, 1]];
      }
    },
    // response the state changes and show/hide the link-point circles
    setState(name, value, item) {
      if (name === 'showAnchors') {
        const anchorPoints = item
          .getContainer()
          .findAll(
            (ele) =>
              ele.get('name') === 'anchor-point' ||
              ele.get('name') === 'anchor-text'
          );
        anchorPoints.forEach((point) => {
          if (value || (point.get('links') > 0 && value)) {
            point.show();
          } else {
            point.hide();
          }
        });
      }
    },
  };
  // eslint-disable-next-line @typescript-eslint/naming-convention
  public static readonly EXTEND_NODE = 'single-node';
}
